﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using UniLua;

namespace TCG
{
	public class DebugWindow : MonoBehaviour 
	{
		private static DebugWindow m_instance = null;

		public static DebugWindow instance
		{
			get
			{
				if (m_instance == null)
				{
					GameObject go = new GameObject ("_TCG_GameDebug");
					GameObject.DontDestroyOnLoad (go);
					m_instance = go.AddComponent<DebugWindow> ();

				}
				return m_instance;
			}
		}

		public void Initialize (ILuaState luaState)
		{
			m_luaState = luaState;

			ThreadStatus status = m_luaState.L_DoFile ("command_line_parser.lua");
			if (status != ThreadStatus.LUA_OK)
			{
				throw new Exception (m_luaState.ToString (-1));
			}
			m_parserFuncRef = LuaTools.RefLuaFunction (m_luaState, -1, "parse_command");

			Application.RegisterLogCallback (delegate (string condition, string stackTrace, LogType type) {
				LogItem logItem = new LogItem ();
				logItem.message = condition;
				logItem.stackTrace = stackTrace;
				if (type == LogType.Log)
				{
					logItem.guiColor = Color.white;
				}
				else if (type == LogType.Warning)
				{
					logItem.guiColor = Color.yellow;
				}
				else
				{
					logItem.guiColor = Color.red;
				}
				if (m_logItems.Count >= MaxItems)
				{
					m_logItems.RemoveAt (0);
				}
				m_logItems.Add (logItem);
			});

			m_wndRect = new Rect (m_padding, m_padding, Screen.width - m_padding * 2, Screen.height - m_padding * 3 - m_inputHeight);
		}

		public bool logWindowEnabled { get; set; }

	    void OnGUI ()
	    {
			if (logWindowEnabled)
			{
		        m_wndRect = GUILayout.Window (LogConsoleWndId, 
				                              new Rect (m_padding, m_padding, Screen.width - m_padding * 2, Screen.height - m_padding * 3 - m_inputHeight), 
				                              LogConsoleWndFunction, 
				                              "log console");
			}
			else
			{
				m_wndRect = new Rect (m_padding, m_padding, Screen.width - m_padding * 2, Screen.height - m_padding * 3 - m_inputHeight);
			}
			GUILayout.Space (m_wndRect.height + m_wndRect.y + m_padding);

			GUILayout.BeginHorizontal ();
			GUILayout.Space (m_padding);
			bool toggleInput = GUILayout.Button ("debug", GUILayout.Width (95), GUILayout.Height (m_inputHeight));
			if (commandLineEnabled)
			{
				m_commandLine = GUILayout.TextField (m_commandLine, GUILayout.Width (Screen.width - m_padding * 2 - 200), GUILayout.Height (m_inputHeight));
				bool execute = GUILayout.Button ("execute", GUILayout.Width (95), GUILayout.Height (m_inputHeight)); 
				GUILayout.Space (m_padding);

				if (execute)
				{
					DoCommand ();
				}
			}
			GUILayout.EndHorizontal ();

			if (toggleInput)
			{
				commandLineEnabled = !commandLineEnabled;
			}
	    }

	    void LogConsoleWndFunction (int windowId)
	    {
	        if (windowId != LogConsoleWndId) return;

	        // show log view
	        Color rawColor = GUI.color;
	        m_scrollPos = GUILayout.BeginScrollView (m_scrollPos);
	        foreach (LogItem _logItem in m_logItems)
	        {
	            GUI.color = _logItem.guiColor;
	            GUILayout.Label (_logItem.message);
	            if (m_stackTraceEnabled)
	            {
	                GUILayout.Label (_logItem.stackTrace);
	            }
	        }
	        GUILayout.EndScrollView ();
	        GUI.color = rawColor;

	        // buttons
	        GUILayout.BeginHorizontal ();
	        if (m_stackTraceEnabled)
	        {
	            if (GUILayout.Button ("hide stack"))
	            {
	                m_stackTraceEnabled = false;
	            }
	        }
	        else
	        {
	            if (GUILayout.Button ("show stack"))
	            {
	                m_stackTraceEnabled = true;
	            }
	        }
	        if (GUILayout.Button ("clear"))
	        {
	            m_logItems.Clear ();
	        }

	        if (GUILayout.Button ("close"))
	        {
				logWindowEnabled = false;
	        }
	        GUILayout.EndHorizontal ();
	    }

		void DoCommand ()
		{
			if (string.IsNullOrEmpty (m_commandLine))
			{
				return;
			}

			m_luaState.PushString (m_commandLine);
			LuaTools.CallLuaRefFunction (m_luaState, m_parserFuncRef, 1, 0, 0);
		}

		class LogItem
		{
			public Color guiColor;
			public string message;
			public string stackTrace;
		}

		bool commandLineEnabled { get; set; }

	    static int LogConsoleWndId = 100;
	    static int MaxItems = 500;
	    IList<LogItem> m_logItems = new List<LogItem> (MaxItems);
	    bool m_stackTraceEnabled = false;
	    
		float m_padding = 10;

		Rect m_wndRect;
	    Vector2 m_scrollPos;

		float m_inputHeight = 25;
		string m_commandLine = string.Empty;

		ILuaState m_luaState = null;
		int m_parserFuncRef = 0;
	}
}
